using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Text;

namespace Universe.Threading
{
    public static class RangeFor<T> where T: struct
    {
        private static Kind TheKind = Kind.Empty;

        static RangeFor()
        {
            if (typeof(T) == typeof(Int16))
                TheKind = Kind.Int16;
            else if (typeof(T) == typeof(Int32))
                TheKind = Kind.Int32;
            else if (typeof(T) == typeof(Int64))
                TheKind = Kind.Int64;
            else if (typeof(T) == typeof(Decimal))
                TheKind = Kind.Decimal;
            /*
            else if (typeof(T) == typeof(UInt16))
                TheKind = Kind.UInt16;
            else if (typeof(T) == typeof(UInt32))
                TheKind = Kind.UInt32;
            else if (typeof(T) == typeof(UInt64))
                TheKind = Kind.UInt64;
            else if (typeof(T) == typeof(Double))
                TheKind = Kind.Double;
            else if (typeof(T) == typeof(Single))
                TheKind = Kind.Single;
             */
        }

        enum Kind
        {
            Empty,
            Int16,
            Int32,
            Int64,
            UInt16,
            UInt32,
            UInt64,
            Decimal,
            Double,
            Single
        }


        public static IEnumerable<T> Create(T from, T to, T step)
        {

            if (TheKind == Kind.Int32)
                return (IEnumerable<T>)new RangeEnumerable_Int32((Int32)(ValueType)from, (Int32)(ValueType)to, (Int32)(ValueType)step);

            if (TheKind == Kind.Int64)
                return (IEnumerable<T>)new RangeEnumerable_Int64((Int64)(ValueType)from, (Int64)(ValueType)to, (Int64)(ValueType)step);

            if (TheKind == Kind.Int16)
                return (IEnumerable<T>)new RangeEnumerable_Int16((Int16)(ValueType)from, (Int16)(ValueType)to, (Int16)(ValueType)step);

            if (TheKind == Kind.Decimal)
                return (IEnumerable<T>)new RangeEnumerable_Decimal((Decimal)(ValueType)from, (Decimal)(ValueType)to, (Decimal)(ValueType)step);



            throw NotSupported;
        }

        public static IEnumerable<T> Forward(T from, T to)
        {

            if (TheKind == Kind.Int32)
                return (IEnumerable<T>)new RangeEnumerable_Int32((Int32)(ValueType)from, (Int32)(ValueType)to, 1);

            if (TheKind == Kind.Int64)
                return (IEnumerable<T>)new RangeEnumerable_Int64((Int64)(ValueType)from, (Int64)(ValueType)to, 1);

            if (TheKind == Kind.Int16)
                return (IEnumerable<T>)new RangeEnumerable_Int16((Int16)(ValueType)from, (Int16)(ValueType)to, 1);

            if (TheKind == Kind.Decimal)
                return (IEnumerable<T>)new RangeEnumerable_Decimal((Decimal)(ValueType)from, (Decimal)(ValueType)to, 1);


            throw NotSupported;
        }

        public static IEnumerable<T> Back(T high, T low)
        {

            if (TheKind == Kind.Int32)
                return (IEnumerable<T>)new RangeEnumerable_Int32((Int32)(ValueType)high, (Int32)(ValueType)low, -1);

            if (TheKind == Kind.Int64)
                return (IEnumerable<T>)new RangeEnumerable_Int64((Int64)(ValueType)high, (Int64)(ValueType)low, -1);

            if (TheKind == Kind.Int16)
                return (IEnumerable<T>)new RangeEnumerable_Int16((Int16)(ValueType)high, (Int16)(ValueType)low, -1);

            if (TheKind == Kind.Decimal)
                return (IEnumerable<T>)new RangeEnumerable_Decimal((Decimal)(ValueType)high, (Decimal)(ValueType)low, -1);



            throw NotSupported;
        }

        public static IEnumerable<T> Any(T start, T end)
        {

            if (TheKind == Kind.Int32)
                return (IEnumerable<T>)RangeEnumerable_Int32.AnyDirection((Int32)(ValueType)start, (Int32)(ValueType)end);

            if (TheKind == Kind.Int64)
                return (IEnumerable<T>)RangeEnumerable_Int64.AnyDirection((Int64)(ValueType)start, (Int64)(ValueType)end);

            if (TheKind == Kind.Int16)
                return (IEnumerable<T>)RangeEnumerable_Int16.AnyDirection((Int16)(ValueType)start, (Int16)(ValueType)end);

            if (TheKind == Kind.Decimal)
                return (IEnumerable<T>)RangeEnumerable_Decimal.AnyDirection((Decimal)(ValueType)start, (Decimal)(ValueType)end);

            throw NotSupported;
        }

        static NotSupportedException NotSupported
        {
            get { return new NotSupportedException("Range enumeration of type '" + typeof (T) + "' is not supported"); }
        }

    }
}
